/****************************************************************************
 *
 *      $Id:  $
 *
 *      Description: Simple milestone 0 code.
 *      		     Libc will need sos_write & sos_read implemented.
 *
 *      Author:      Ben Leslie
 *
 ****************************************************************************/

#include <stdarg.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include "ttyout.h"

#include <sel4/sel4.h>

#include <serial/serial.h>



size_t sos_putString(const char* string, size_t count);

void ttyout_init(void) {
    /* Perform any initialisation you require here */

}

static size_t sos_debug_print(const void *vData, long int position, size_t count, void *handle) {
    size_t i;
    const char *realdata = vData;
    for (i = 0; i < count; i++)
        seL4_DebugPutChar(realdata[i]);
    return count;
}

size_t sos_write(void *vData, long int position, size_t count, void *handle) {

    const char *realdata = vData;

    return sos_putString(realdata, count);

}

size_t sos_read(void *vData, long int position, size_t count, void *handle) {
    //implement this to use your syscall
    return 0;
}

void abort(void) {
    sos_debug_print("sos abort()ed", 0, strlen("sos abort()ed"), 0);
    seL4_DebugHalt();
    while (1)
        ; /* We don't return after this */
}


size_t sos_putString(const char* string, size_t count){

	int i;

    seL4_MessageInfo tag = { { .length = 40, .extraCaps = 0 } };
    tag.label = seL4_NoFault;

    /*
    the simple IPC protocol works this way :
    msg[1] is the length of the string, msg[0] is taken by the syscall number
    the rest are the actual string's characters
    if the message cannot fit into the IPC buffer, it is silently truncated, splitting the message up can solve the problem.

    note : although the printf ultimately sends one character at time, the prototype of sos_write does suggets that it should
    handle strings... not just a char at a time.

    */

    //syscall 3 stands for putString
    seL4_SetMR(0, 3);

    //the first two words of the IPC buffer (aside from the tag) are already occupied by length and syscall number
    //Strictly speaking, one should stuff two characters in a word for performance

    for(i=0;i<count && i< (seL4_MsgMaxLength- 2) && string[i] != '\0';i++){
    	seL4_SetMR(i+2, string[i]);
    }

    seL4_SetMR(i+2,'\0');

    //record the length
    tag.length = i+2;

    seL4_SetMR(1,i+1);
    seL4_SetTag(tag);

    //make the call
    seL4_Call(SYSCALL_ENDPOINT_SLOT, tag);

    //return the number of bytes actually sent
    //handling of dropped bytes is not considered
	return seL4_GetMR(0);
}


